use std::fmt;

struct MyStruct {
    pub data: String,
}

impl AsRef<MyStruct> for MyStruct {
    fn as_ref(&self) -> &Self {
        self
    }
}

struct More {
    pub id: String,
    pub data: MyStruct,
}

impl AsRef<MyStruct> for More {
    fn as_ref(&self) -> &MyStruct {
        &self.data
    }
}

impl fmt::Display for MyStruct {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "MyStruct: {}", self.data)
    }
}

/*
 * 错误的代码
impl AsRef<MyStruct> for String {
    fn as_ref(&self) -> &MyStruct {
        &MyStruct {
            data: self.to_owned(),
        }
    }
}
*/

fn use_as_ref(val: impl AsRef<MyStruct>) {
    println!("ref is: {}", val.as_ref());
    println!("data is: {}", val.as_ref().data);
}

fn main() {
    let mydata = MyStruct {
        data: "ABCD".to_string(),
    };

    let more = More {
        id: "alan".to_string(),
        data: MyStruct {
            data: "CCCD".to_string(),
        },
    };

    use_as_ref(mydata);
    use_as_ref(more);
}
